package pl.maciejziarko.mshare.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Component;
import pl.maciejziarko.mshare.domain.Resource;
import pl.maciejziarko.mshare.persistence.ResourceMapper;
import pl.maciejziarko.mshare.service.exception.InvalidResourceException;
import pl.maciejziarko.mshare.service.exception.ResourceNotFoundException;
import pl.maciejziarko.mshare.service.exception.ResourceServiceException;
import pl.maciejziarko.mshare.service.processors.ProcessingException;
import pl.maciejziarko.mshare.service.processors.Processor;

/**
 * @author Maciej Ziarko
 */
@Component
public class MShareResourceService implements ResourceService {

    private ResourceMapper resourceMapper;
    private Processor<Resource> resourceProcessor;

    @Autowired
    public MShareResourceService(ResourceMapper resourceMapper, Processor<Resource> resourceProcessor) {
        this.resourceMapper = resourceMapper;
        this.resourceProcessor = resourceProcessor;
    }

    @Override
    public Resource getResource(long id) throws ResourceNotFoundException, ResourceServiceException {
        try {
            Resource resource = resourceMapper.selectResource(id);
            if (resource == null) {
                throw new ResourceNotFoundException("Resource with id: [{}] is not found", id);
            }
            return resource;
        } catch (DataAccessException e) {
            throw new ResourceServiceException();
        }
    }

    @Override
    public Resource addResource(Resource resource) throws InvalidResourceException, ResourceServiceException {
        try {
            Resource processedResource = resourceProcessor.process(resource);
            int affectedRows = resourceMapper.insertResource(processedResource);
            if (affectedRows != 1) {
                throw new ResourceServiceException();
            }
            return processedResource;
        } catch (DataIntegrityViolationException e) {
            throw new InvalidResourceException();
        } catch (DataAccessException | ProcessingException e) {
            throw new ResourceServiceException();
        }
    }

    @Override
    public void removeAllResources() throws ResourceServiceException {
        try {
            resourceMapper.deleteAllResources();
        } catch (DataAccessException e) {
            throw new ResourceServiceException();
        }
    }

    @Override
    public long countResources() throws ResourceServiceException {
        try {
            return resourceMapper.selectResourcesCount();
        } catch (DataAccessException e) {
            return 0;
        }
    }
}
